﻿using System;
using HouseKeeperCore.Hierarchical;

namespace BillSplitter
{
    /// <summary>
    ///  Event that happens to have a structural change made
    /// </summary>
    public class StructureEvent : BillEvent
    {
        #region Enumerations
        
        /// <summary>
        ///  Type of the structural change
        /// </summary>
        public enum ChangeType
        {
            AddEntity,      // Adds a user or a group, it's on the solver to differentiate it
            RemoveEntity,   // Removes a user or a group
            AddToGroup,     // Adds an entity (either a user or a group) to a group
            RemoveFromGroup // Removes an entity from a group
        }

        #endregion

        #region Properties

        /// <summary>
        ///  The type of the change involved in this event
        /// </summary>
        public ChangeType Action { get; private set; }

        /// <summary>
        ///  The entity/user that is involved in the change
        /// </summary>
        public TaggedEntity Entity { get; private set; }

        /// <summary>
        ///  The group that is involved in the change
        /// </summary>
        public BillGroup Group { get; private set; }

        #endregion

        #region Constructors

        /// <summary>
        ///  Instantiates a structure event with specified time
        /// </summary>
        /// <param name="time">When the event happens</param>
        private StructureEvent(DateTime? time)
            : base(time)
        {
        }

        #endregion

        #region Methods

        /// <summary>
        ///  Creates an event that adds the specified entity (either user or group) to the event receiver
        /// </summary>
        /// <param name="time">When the event happens</param>
        /// <param name="entity">The entity to add</param>
        /// <returns>The event</returns>
        public static StructureEvent AddEntity(DateTime? time, TaggedEntity entity)
        {
            var e = new StructureEvent(time)
                        {
                            Action = ChangeType.AddEntity, Entity = entity
                        };
            return e;
        }

        /// <summary>
        ///  Creates an event that removes the specified entity from the event receiver
        /// </summary>
        /// <param name="time">When the event happens</param>
        /// <param name="entity">The entity to remove</param>
        /// <returns>The event</returns>
        public static StructureEvent RemoveEntity(DateTime? time, TaggedEntity entity)
        {
            var e = new StructureEvent(time)
                        {
                            Action = ChangeType.RemoveEntity, Entity = entity
                        };
            return e;
        }

        /// <summary>
        ///  Creates a structure event that adds the specified entity to the specified group
        /// </summary>
        /// <param name="time">When the event happens</param>
        /// <param name="entity">The entity to add</param>
        /// <param name="group">The group</param>
        /// <returns>The event</returns>
        public static StructureEvent AddToGroup(DateTime? time, TaggedEntity entity, BillGroup group)
        {
            var e = new StructureEvent(time)
 						{
							Action = ChangeType.AddToGroup, Entity = entity, Group = group
						};
            return e;
        }

        /// <summary>
        ///  Creates a structure event that removes the specified entity from the specified group
        /// </summary>
        /// <param name="time">When the event happens</param>
        /// <param name="entity">The entity to remove</param>
        /// <param name="group">The group</param>
        /// <returns>The event</returns>
        public static StructureEvent RemoveFromGroup(DateTime? time, TaggedEntity entity, BillGroup group)
        {
            var e = new StructureEvent(time)
 						{
							Action = ChangeType.RemoveFromGroup, Entity = entity, Group = group
						};
            return e;
        }

        #endregion
    }
}
